package org.openmobo.playn.poc1.core;

import static playn.core.PlayN.*;

import java.util.ArrayList;
import java.util.logging.Logger;

import org.jbox2d.collision.shapes.CircleShape;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.FixtureDef;

import playn.core.Canvas;
import playn.core.CanvasImage;
import playn.core.CanvasLayer;
import playn.core.Font;
import playn.core.Game;
import playn.core.GroupLayer;
import playn.core.Image;
import playn.core.ImageLayer;
import playn.core.Layer;
import playn.core.Pointer;
import playn.core.TextFormat;
import playn.core.TextLayout;

import org.jbox2d.collision.shapes.CircleShape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.FixtureDef;
import org.jbox2d.dynamics.World;

public class Poc1ConcordanciaNominal implements Game {
	private GroupLayer base;
	private World world;
	private float pWidth, pHeight;
	private int width, height;
	private TitleSlide s1;
	private float physUnitPerScreenUnit;
	private GroupLayer slideLayer;
	Logger log = Logger.getLogger("Poc1");

	class Ball {
		public ImageLayer layer;
		float angle = 0.0f;
		public Body body;

		public Ball(Image image, float x, float y) {
			float radius = 0.5f;
			layer = graphics().createImageLayer(image);
			layer.setOrigin(image.width() / 2f, image.height() / 2f);
			layer.setScale((radius * 2) / image.width(),
					(radius * 2) / image.height());
			layer.setTranslation(x, y);

			BodyDef bodyDef = new BodyDef();
			bodyDef.type = BodyType.DYNAMIC;
			bodyDef.position = new Vec2(x, y);
			body = world.createBody(bodyDef);
			FixtureDef fixtureDef = new FixtureDef();
			fixtureDef.shape = new CircleShape();
			fixtureDef.shape.m_radius = radius;
			fixtureDef.density = 1.0f;
			fixtureDef.friction = 0.3f;
			body.createFixture(fixtureDef);
			body.setTransform(new Vec2(x, y), angle);
		}

		public void paint(float delta) {
			layer.setTranslation(body.getPosition().x, body.getPosition().y);
			angle += delta * 0.1f;
			layer.setRotation(angle);
//			log.info("x="+body.getPosition().x+";y="+body.getPosition().y);
		}
	}
	
	class Text {

		public Layer layer;
		private Body body;
		private Body ground;

		public Text(String text, float x, float y) {
			// add some text to said soothing background
			final float MARGIN = 10;
			float xpos = MARGIN;// , maxYPos = 0;
			float ypos = 0;
			Font font = graphics().createFont("Helvetica", Font.Style.BOLD, 12f);
			TextFormat format = new TextFormat().withFont(font);
			TextLayout layout = graphics().layoutText(text,
					format);
			layer = createTextLayer(layout);

			// centering text
//			xpos = (width - layout.width()) * 0.5f;
//			ypos = height * 0.2f;
//			layer.setScale(1f / physUnitPerScreenUnit);
			layer.setOrigin(layout.width() / 2, layout.height());
			layer.setTranslation(x,y);
			float px = x * physUnitPerScreenUnit;
			float py = y * physUnitPerScreenUnit;
			BodyDef bodyDef = new BodyDef();
			bodyDef.type = BodyType.DYNAMIC;
			bodyDef.position = new Vec2(px, py);
			body = world.createBody(bodyDef);
			FixtureDef fixtureDef = new FixtureDef();
//			fixtureDef.shape = new CircleShape();
//			fixtureDef.shape.m_radius = layout.height() * physUnitPerScreenUnit;
			PolygonShape shape = new PolygonShape();
			fixtureDef.shape = new PolygonShape();
			shape.setAsBox(layout.height() * physUnitPerScreenUnit * 0.5f, 
					layout.width() * physUnitPerScreenUnit * 0.5f);
			fixtureDef.shape = shape;
			fixtureDef.density = 1.0f;
//			fixtureDef.friction = 0.3f;
			fixtureDef.friction = 0.03f;
			body.createFixture(fixtureDef);
			body.setTransform(new Vec2(px, py), 0f);
		}

		protected Layer createTextLayer(TextLayout layout) {
			CanvasLayer layer = graphics().createCanvasLayer(
					(int) Math.ceil(layout.width()),
					(int) Math.ceil(layout.height()));
			layer.canvas().drawText(layout, 0, 0);
			return layer;
		}

		public void paint(float delta) {
			float px = body.getPosition().x / physUnitPerScreenUnit;
			float py = body.getPosition().y / physUnitPerScreenUnit;
			layer.setTranslation(px, py);
//			log.info("px="+px+";py="+py);
			// angle += delta * 0.1f;
			// layer.setRotation(angle);
		}
	}
	
	ArrayList<Ball> balls = new ArrayList<Ball>();
	ArrayList<Text> texts = new ArrayList<Text>();
	Image ballImage;
	private GroupLayer ballLayer;
	private Body ground;

	@Override
	public void init() {
		// create and add background image layer
		// Image bgImage = assetManager().getImage("images/bg.png");
		// width = bgImage.width();
		// height = bgImage.height();
		width = 640;
		height = 480;
		physUnitPerScreenUnit = 1 / 26.666667f;
		pWidth = width * physUnitPerScreenUnit;
		pHeight = height * physUnitPerScreenUnit;
		// ImageLayer bgLayer = graphics().createImageLayer(bgImage);
		// bgLayer.setSize(width, height);
		// graphics().rootLayer().add(bgLayer);
		Vec2 gravity = new Vec2(0.0f, 10.0f);
		world = new World(gravity, true);
		// world.setWarmStarting(true);
		// world.setAutoClearForces(true);

		CanvasImage bgImage = graphics().createImage(width, height);
		Canvas canvas = bgImage.canvas();
		canvas.setFillColor(0xff87ceeb);
		canvas.fillRect(0, 0, width, height);
		ImageLayer bgLayer = graphics().createImageLayer(bgImage);
		graphics().rootLayer().add(bgLayer);

		ballImage = assetManager().getImage("images/ball.png");
		ballLayer = graphics().createGroupLayer();
		ballLayer.setScale(1f / physUnitPerScreenUnit);
		graphics().rootLayer().add(ballLayer);
		slideLayer = graphics().createGroupLayer();
		graphics().rootLayer().add(slideLayer);
		pointer().setListener(new Pointer.Adapter() {
			@Override
			public void onPointerEnd(Pointer.Event event) {
				Ball ball = new Ball(ballImage, physUnitPerScreenUnit
						* event.x(), physUnitPerScreenUnit * event.y());
				balls.add(ball);
				ballLayer.add(ball.layer);
				log.info("balls=" + balls.size());
				Text text = new Text("teste",event.x(), event.y());
				texts.add(text);
				log.info("text=" + texts.size());
				slideLayer.add(text.layer);
				log.info("text added");
			}
		});
		
	    ground = world.createBody(new BodyDef());
	    PolygonShape bottom = new PolygonShape();
	    bottom.setAsEdge(new Vec2(0, pHeight * 0.9f), new Vec2(pWidth, pHeight * 0.8f));
	    ground.createFixture(bottom, 0.0f);
	    
		CanvasImage ground = graphics().createImage(width, height);
		Canvas groundCanvas = bgImage.canvas();
		groundCanvas.setFillColor(0xff000000);
		groundCanvas.drawLine(0, height * 0.9f, width, height * 0.8f);
		ImageLayer groundLayer = graphics().createImageLayer(ground);
		graphics().rootLayer().add(groundLayer);
	    
//		slideLayer = graphics().createGroupLayer();
//		slideLayer.setScale(1f / physUnitPerScreenUnit);
//		s1 = new TitleSlide();
//		ballLayer.add(s1.getLayer());
//		slideLayer.add(s1.getLayer());
//		graphics().rootLayer().add(slideLayer);

	}

	@Override
	public void paint(float alpha) {
		// the background automatically paints itself, so no need to do anything
		// here!
//		s1.paint(alpha);
		for (Ball ball : balls) {
			ball.paint(alpha);
		}
		for (Text text : texts) {
			text.paint(alpha);
		}
	}

	@Override
	public void update(float delta) {
		world.step(0.033f, 10, 10);
		ArrayList<Ball> removeBalls = new ArrayList<Ball>();
		for (Ball ball : balls) {
			if (ball.layer.transform().translation().y() >= (height - ballImage
					.height()) * physUnitPerScreenUnit) {
				ballLayer.remove(ball.layer);
				world.destroyBody(ball.body);
				removeBalls.add(ball);
			}
		}
		for (Ball ball : removeBalls) {
			balls.remove(ball);
		}
		removeBalls.clear();
		ArrayList<Text> removeTexts = new ArrayList<Text>();
		for (Text text : texts) {
			if (text.layer.transform().translation().y() > height) {
				slideLayer.remove(text.layer);
				world.destroyBody(text.body);
				removeTexts.add(text);
			}
		}
		for (Text text : removeTexts) {
			texts.remove(text);
		}
		removeTexts.clear();
	}

	@Override
	public int updateRate() {
		return 25;
	}

	class TitleSlide {

		private Layer textLayer;
		private Body body;
		private Body ground;

		public TitleSlide() {
			// add some text to said soothing background
			final float MARGIN = 10;
			float xpos = MARGIN;// , maxYPos = 0;
			float ypos = 0;
			// Font font = graphics()
			// .createFont("Helvetica", Font.Style.BOLD, 32f);
			Font font = graphics().createFont("Helvetica", Font.Style.BOLD, 6f);
			TextFormat format = new TextFormat().withFont(font);
			TextLayout layout = graphics().layoutText("A língua em foco",
					format);
			textLayer = createTextLayer(layout);

			// centering text
			xpos = (width - layout.width()) * 0.5f;
			ypos = height * 0.2f;
			// textLayer.setScale(1f / physUnitPerScreenUnit);
			textLayer.setTranslation(0,0);

			BodyDef bodyDef = new BodyDef();
			bodyDef.type = BodyType.DYNAMIC;
			// xpos *= physUnitPerScreenUnit;
			// ypos *= physUnitPerScreenUnit;
			bodyDef.position = new Vec2(width * 0.5f, 0f);
			body = world.createBody(bodyDef);
			FixtureDef fixtureDef = new FixtureDef();
			fixtureDef.shape = new CircleShape();
			fixtureDef.shape.m_radius = layout.width();
			fixtureDef.density = 1.0f;
			fixtureDef.friction = 0.3f;
			body.createFixture(fixtureDef);
			body.setTransform(new Vec2(width * 0.5f, 0f), 0f);

			// // Adding the ground
			// ground = world.createBody(new BodyDef());
			// PolygonShape bottom = new PolygonShape();
			// bottom.setAsEdge(new Vec2(0, height * 0.5f), new Vec2(width,
			// height * 0.5f + 10));
			// ground.createFixture(bottom, 0.0f);

			// Adding a debug canvas.
//			CanvasImage canvasImage = graphics().createImage(width, height);
//			Canvas canvas = canvasImage.canvas();
//			canvas.setFillColor(0xff0000ff);
//			canvas.fillRect(5, height * 0.5f, width - 10, 10);
//			ImageLayer canvasLayer = graphics().createImageLayer(canvasImage);
//			graphics().rootLayer().add(canvasLayer);

		}

		protected Layer createTextLayer(TextLayout layout) {
			CanvasLayer layer = graphics().createCanvasLayer(
					(int) Math.ceil(layout.width()),
					(int) Math.ceil(layout.height()));
			layer.canvas().drawText(layout, 0, 0);
			return layer;
		}

		public void paint(float delta) {
			textLayer
					.setTranslation(body.getPosition().x, body.getPosition().y);
			// angle += delta * 0.1f;
			// layer.setRotation(angle);
		}

		public Layer getLayer() {
			return textLayer;
		}
	}
}
